home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / TransSkel Pascal 2.5 / TransDisplay / EventLog / EventLog.p < prev    next >
Encoding:
Text File  |  1994-12-08  |  20.6 KB  |  970 lines  |  [TEXT/PJMM]

  1. {    EventLog - TransDisplay event-logging demonstration program}
  2.  
  3. {    The project should include EventLog.p (this file), TransDisplay.p}
  4. {    (or a library made from TransDisplay.p), TransSkel.p (or a library}
  5. {    made from TransSkel.ps), and Runtime.lib and Interface.lib.  Also, you'll}
  6. {    need to set the run options to use the file EventLog.proj.rsrc as a resource}
  7. {    file. }
  8.  
  9. {    8 November 1986    Paul DuBois}
  10.  
  11. {11 January 1987    Ported to LightSpeed Pascal by Owen Hartnett    }
  12. {Ωhm Software Co., 163 Richard Drive, Tiverton, RI 02878        }
  13.  
  14. {1994: Ingemar added MultiFinder and Apple event logging}
  15.  
  16. program EventLog;
  17.  
  18.     uses
  19. {$IFC UNDEFINED THINK_PASCAL}
  20.         Memtypes, Quickdraw, OSIntf, ToolIntf, PackIntf, 
  21. {$ENDC}
  22.         TransSkel, TransDisplay;
  23.  
  24.     const
  25.  
  26.                     { declare zoom box part codes }
  27.  
  28.         inZoomIN = 7;
  29.         inZoomOut = 8;
  30.  
  31.         maxButton = 16;
  32.  
  33.         helpTextRes = 1000;        { help text resource number }
  34.         aboutAlrtRes = 1000;    { About... alert resource number }
  35.  
  36.                     { Menu resource numbers }
  37.  
  38.         fileMenuRes = 1000;
  39.         editMenuRes = 1001;
  40.         logMenuRes = 1002;
  41.  
  42.                     { Window resource numbers }
  43.  
  44.         LogWindRes = 1000;
  45.         helpWindRes = 1001;
  46.         SelectWindRes = 1002;
  47.  
  48.             { File menu item numbers }
  49.  
  50.         showLog = 1;    { make windows visible/bring to front }
  51.         showHelp = 2;
  52.         ShowSelect = 3;
  53.         quit = 5;
  54.  
  55.                 { Edit menu item numbers }
  56.  
  57.         undo = 1;
  58.         cut = 3;
  59.         copy = 4;
  60.         paste = 5;
  61.         clear = 6;
  62.  
  63.                 { Log menu item numbers }
  64.  
  65.         logEvents = 1;        { whether events are logged }
  66.         excludeLWind = 2;
  67.         flushLog = 4;                { flush log output }
  68.         wrapStyle = 6;            { word wrap or not }
  69.         leftJust = 8;                { justification }
  70.         centerJust = 9;
  71.         rightJust = 10;
  72.         small = 12;                { text size }
  73.         medium = 13;
  74.         large = 14;
  75.         top = 16;                    { scroll home }
  76.         bottom = 17;                { scroll to bottom }
  77.  
  78.     type
  79.         booleanPtr = ^Boolean;
  80.         CtrlInfoPtr = ^CtrlInfoRec;
  81.         CtrlInfoRec = record
  82.                 loc: Point;        { upper left of control }
  83.                 title: Str255;        { control title }
  84.                 flagAddr: booleanPtr;    { associated boolean }
  85.                 ctrl: ControlHandle;        { associated control }
  86.                 subInfo: CtrlInfoPtr;    { subsidiary control }
  87.             end;
  88.  
  89.  
  90.     var
  91.         selectWind, helpWind, logWind: WindowPtr;
  92.             { event selection window }
  93.             { help text window }
  94.             { log output window }
  95.         fileMenu, editMenu, logMenu: MenuHandle;
  96.         reportEvents, excludeLog: Boolean;
  97.         { report events or not }
  98.         { exclude log window events or not }
  99.         logFont, logSize: integer;
  100.         logWrap, logJust: integer;
  101.         rMouseDown, rMouseMods, rMouseWind, rMouseLoc: Boolean;
  102.                             { event type selection flags }
  103.         rMousePart, rMouseSys, rMouseUp, rKeyDown, rKDMods: Boolean;
  104.         rAutoKey, rAKMods, rUpdate, rActivate, rDisk: Boolean;
  105.         rMultiFinder, rAppleEvt: Boolean;
  106.         currentPort: GrafPtr;
  107.  
  108. {    Control information.  The last field is used to tell which controls}
  109. {    are "owned" by another.  When the owner is unchecked, all the owned}
  110. {    controls go dim.}
  111.  
  112.         ctrlInfo: array[0..maxButton] of CtrlInfoRec;
  113.  
  114. {    Window that was in front last time checked    }
  115.  
  116.         lastFront: WindowPtr;
  117.         h: Handle;
  118.         dummy: Boolean;
  119.  
  120. {    Do in Pascal what can be done in C as static initializations.  }
  121. {Ingemar: IMHO, this should be done with a DITL resource!}
  122.  
  123.     procedure SetupStuff;
  124.  
  125.     begin
  126.         rMouseDown := true;
  127.         rMouseMods := false;
  128.         rMouseWind := true;
  129.         rMouseLoc := false;
  130.         rMousePart := true;
  131.         rMouseSys := false;
  132.         rMouseUP := false;
  133.         rKeyDown := true;
  134.         rKDMods := false;
  135.         rAutoKey := true;
  136.         rAKMods := false;
  137.         rUpdate := true;
  138.         rActivate := true;
  139.         rDisk := true;
  140.         rMultiFinder := true;
  141.         rAppleEvt := true;
  142.  
  143.         with ctrlInfo[0] do
  144.             begin
  145.                 loc.v := 5;
  146.                 loc.h := 10;
  147.                 title := 'Mouse Down';
  148.                 flagAddr := @rMouseDown;
  149.                 ctrl := nil;
  150.                 subInfo := nil;
  151.             end;
  152.  
  153.         with ctrlInfo[1] do
  154.             begin
  155.                 loc.v := 25;
  156.                 loc.h := 30;
  157.                 title := 'Modifiers';
  158.                 flagAddr := @rMouseMods;
  159.                 ctrl := nil;
  160.                 subInfo := @ctrlInfo[0];
  161.             end;
  162.  
  163.         with ctrlInfo[2] do
  164.             begin
  165.                 loc.v := 45;
  166.                 loc.h := 30;
  167.                 title := 'Window';
  168.                 flagAddr := @rMouseWind;
  169.                 ctrl := nil;
  170.                 subInfo := @ctrlInfo[0];
  171.             end;
  172.  
  173.         with ctrlInfo[3] do
  174.             begin
  175.                 loc.v := 65;
  176.                 loc.h := 30;
  177.                 title := 'Location';
  178.                 flagAddr := @rMouseLoc;
  179.                 ctrl := nil;
  180.                 subInfo := @ctrlInfo[0];
  181.             end;
  182.  
  183.         with ctrlInfo[4] do
  184.             begin
  185.                 loc.v := 85;
  186.                 loc.h := 30;
  187.                 title := 'Part Code';
  188.                 flagAddr := @rMousePart;
  189.                 ctrl := nil;
  190.                 subInfo := @ctrlInfo[0];
  191.             end;
  192.  
  193.         with ctrlInfo[5] do
  194.             begin
  195.                 loc.v := 105;
  196.                 loc.h := 30;
  197.                 title := 'System Clicks';
  198.                 flagAddr := @rMouseSys;
  199.                 ctrl := nil;
  200.                 subInfo := @ctrlInfo[0];
  201.             end;
  202.  
  203.         with ctrlInfo[6] do
  204.             begin
  205.                 loc.v := 125;
  206.                 loc.h := 10;
  207.                 title := 'Mouse Up';
  208.                 flagAddr := @rMouseUp;
  209.                 ctrl := nil;
  210.                 subInfo := nil;
  211.             end;
  212.  
  213.         with ctrlInfo[7] do
  214.             begin
  215.                 loc.v := 5;
  216.                 loc.h := 160;
  217.                 title := 'Key Down';
  218.                 flagAddr := @rKeyDown;
  219.                 ctrl := nil;
  220.                 subInfo := nil;
  221.             end;
  222.  
  223.         with ctrlInfo[8] do
  224.             begin
  225.                 loc.v := 25;
  226.                 loc.h := 180;
  227.                 title := 'Modifiers';
  228.                 flagAddr := @rKDMods;
  229.                 ctrl := nil;
  230.                 subInfo := @ctrlInfo[7];
  231.             end;
  232.  
  233.         with ctrlInfo[9] do
  234.             begin
  235.                 loc.v := 45;
  236.                 loc.h := 180;
  237.                 title := 'AutoKey';
  238.                 flagAddr := @rAutoKey;
  239.                 ctrl := nil;
  240.                 subInfo := nil;
  241.             end;
  242.  
  243.         with ctrlInfo[10] do
  244.             begin
  245.                 loc.v := 65;
  246.                 loc.h := 180;
  247.                 title := 'Modifiers';
  248.                 flagAddr := @rAKMods;
  249.                 ctrl := nil;
  250.                 subInfo := @ctrlInfo[9];
  251.             end;
  252.  
  253.         with ctrlInfo[11] do
  254.             begin
  255.                 loc.v := 85;
  256.                 loc.h := 160;
  257.                 title := 'Update';
  258.                 flagAddr := @rUpdate;
  259.                 ctrl := nil;
  260.                 subInfo := nil;
  261.             end;
  262.  
  263.         with ctrlInfo[12] do
  264.             begin
  265.                 loc.v := 105;
  266.                 loc.h := 160;
  267.                 title := 'Activate';
  268.                 flagAddr := @rActivate;
  269.                 ctrl := nil;
  270.                 subInfo := nil;
  271.             end;
  272.  
  273.         with ctrlInfo[13] do
  274.             begin
  275.                 loc.v := 125;
  276.                 loc.h := 160;
  277.                 title := 'Disk';
  278.                 flagAddr := @rDisk;
  279.                 ctrl := nil;
  280.                 subInfo := nil;
  281.             end;
  282.  
  283.         with ctrlInfo[14] do
  284.             begin
  285.                 loc.v := 145;
  286.                 loc.h := 160;
  287.                 title := 'Suspend/Resume';
  288.                 flagAddr := @rMultiFinder;
  289.                 ctrl := nil;
  290.                 subInfo := nil;
  291.             end;
  292.  
  293.         with ctrlInfo[15] do
  294.             begin
  295.                 loc.v := 165;
  296.                 loc.h := 160;
  297.                 title := 'Apple events';
  298.                 flagAddr := @rAppleEvt;
  299.                 ctrl := nil;
  300.                 subInfo := nil;
  301.             end;
  302.  
  303.         lastFront := nil;
  304.     end;
  305.  
  306. {    Print information about a window.  If it's a window with a title,}
  307. {    print the title.  Print whether it's a}
  308. {    desk accessory window.}
  309.  
  310.     procedure WindowInfo (theWind: WindowPeek);
  311.  
  312.         var
  313.             title: Str255;
  314.  
  315.     begin
  316.         GetWTitle(WindowPtr(theWind), title);
  317.         if length(title) > 0 then            { window has title }
  318.             begin
  319.                 DisplayChar(' ');
  320.                 DisplayString(title);
  321.             end;
  322.         if theWind^.windowKind < 0 then
  323.             DisplayString(' (DA)');
  324.     end;
  325.  
  326.     procedure Modifiers (mods: integer);
  327.  
  328.     begin
  329.         DisplayString(' mods ($');
  330.         DisplayHexInt(mods);
  331.         DisplayChar(')');
  332.     end;
  333.  
  334.     procedure MouseLoc (thePt: Point; thePort: GrafPtr);
  335.  
  336.         var
  337.             savePort: GrafPtr;
  338.  
  339.     begin
  340.         GetPort(savePort);
  341.         SetPort(thePort);
  342.         GlobalToLocal(thePt);
  343.         SetPort(savePort);
  344.         if rMouseLoc then
  345.             begin
  346.                 DisplayString(' loc (');
  347.                 DisplayInt(thePt.h);
  348.                 DisplayString(', ');
  349.                 DisplayInt(thePt.v);
  350.                 DisplayChar(')');
  351.             end;
  352.     end;
  353.  
  354. {    Mouse click.  Get the window that the click occurred in, and the}
  355. {    part of the window.}
  356.  
  357. {    Make sure to get all the part codes!  (incl. zoom box stuff)}
  358.  
  359.     procedure ReportMouse (theEvent: EventRecord);
  360.  
  361.         var
  362.             evtPt: Point;
  363.             evtpart: integer;
  364.             evtport: GrafPtr;
  365.  
  366.     begin
  367.         evtPt := theEvent.where;
  368.         evtPart := FindWindow(evtPt, evtPort);
  369.         if not excludeLog or (evtPort <> logWind) then
  370.             begin
  371.                 DisplayString('Mouse Click');
  372.                 case evtPart of
  373.                     inSysWindow: 
  374.  
  375. {    Click in a desk accessory window.}
  376.  
  377.                         if rMouseSys then
  378.                             begin
  379.                                 if rMousePart then
  380.                                     DisplayString(' in system window:');
  381.                                 if rMouseWind then
  382.                                     WindowInfo(WindowPeek(evtPort));
  383.                                 MouseLoc(evtPt, evtport);
  384.                             end;
  385.                     inDesk: 
  386.  
  387. {    Click in desk top.}
  388.  
  389.                         if rMousePart then
  390.                             DisplayString(' in desktop');
  391.                     inMenuBar: 
  392.  
  393. {    Click in menu bar.}
  394.  
  395.                         if rMousePart then
  396.                             DisplayString(' in menu bar');
  397.                     inGrow: 
  398.  
  399. {    Click in grow box.}
  400.  
  401.                         begin
  402.                             if rMousePart then
  403.                                 DisplayString(' in grow region:');
  404.                             if rMouseWind then
  405.                                 WindowInfo(WindowPeek(evtPort));
  406.                             MouseLoc(evtPt, evtPort);
  407.                         end;
  408.                     inDrag: 
  409.  
  410. {    Click in title bar.}
  411.  
  412.                         begin
  413.                             if rMousePart then
  414.                                 DisplayString(' in drag region:');
  415.                             if rMouseWind then
  416.                                 WindowInfo(WindowPeek(evtPort));
  417.                         end;
  418.                     inGoAway: 
  419.  
  420. {    Click in close box.}
  421.  
  422.                         begin
  423.                             if rMousePart then
  424.                                 DisplayString(' in close box:');
  425.                             if rMouseWind then
  426.                                 WindowInfo(WindowPeek(evtPort));
  427.                         end;
  428.                     inZoomIn: 
  429.  
  430. {    Click in zoom-in box.}
  431.  
  432.                         begin
  433.                             if rMousePart then
  434.                                 DisplayString(' in zoom-in box:');
  435.                             if rMouseWind then
  436.                                 WindowInfo(WindowPeek(evtPort));
  437.                         end;
  438.                     inZoomOut: 
  439.  
  440. {    Click in zoom-out box.}
  441.  
  442.                         begin
  443.                             if rMousePart then
  444.                                 DisplayString(' in zoom-out box:');
  445.                             if rMouseWind then
  446.                                 WindowInfo(WindowPeek(evtPort));
  447.                         end;
  448.                     inContent: 
  449.  
  450. {    Click in content region.}
  451.  
  452. {    (Might also check in in control, and if so, print control information)}
  453.  
  454.                         begin
  455.                             if rMousePart then
  456.                                 DisplayString(' in content region:');
  457.                             if rMouseWind then
  458.                                 WindowInfo(WindowPeek(evtPort));
  459.                             MouseLoc(evtPt, evtPort);
  460.                         end;
  461.                     otherwise
  462.                 end;
  463.                 if rMouseMods then
  464.                     Modifiers(theEvent.modifiers);
  465.                 DisplayLn;
  466.             end;
  467.     end;
  468.  
  469.     procedure ReportKey (what: integer; c: char; mods: integer; modFlag: Boolean);
  470.     begin
  471.         if what = keyDown then
  472.             DisplayString('Key Down: char "')
  473.         else
  474.             DisplayString('Autokey: char"');
  475.         DisplayChar(c);
  476.         DisplayString('" ');
  477.         if modFlag then
  478.             Modifiers(mods);
  479.         Displayln;
  480.     end;
  481.  
  482.     procedure ReportActivate (theWind: WindowPtr; mods: integer);
  483.  
  484.     begin
  485.         if BitAnd(mods, activeFlag) <> 0 then
  486.             DisplayString('Activate:')
  487.         else
  488.             DisplayString('Deactivate:');
  489.         WindowInfo(WindowPeek(theWind));
  490.         DisplayLn;
  491.     end;
  492.  
  493.     procedure ReportUpdate (theWind: WindowPtr);
  494.  
  495.     begin
  496.         DisplayString('Update:');
  497.         WindowInfo(WindowPeek(theWind));
  498.         Displayln;
  499.     end;
  500.  
  501. {    General event logger}
  502.  
  503.     function LogEvent (theEvt: EventRecord): Boolean;
  504.  
  505.         const
  506.             kHighLevelEvent = 23;
  507.  
  508.         var
  509.             theEvent: EventRecord;
  510.             evtPt: Point;
  511.             evtPort: GrafPtr;
  512.             evtpart: integer;
  513.             evtChar: char;
  514.             evtMods: integer;
  515.             r: Rect;
  516.             savePort: GrafPtr;
  517.  
  518.     begin
  519.         if reportEvents = false then
  520.             LogEvent := false
  521.         else
  522.             begin
  523.                 theEvent := theEvt;
  524.                 evtPt := theEvent.where;
  525.                 case theEvent.what of
  526.  
  527.                     mouseDown:
  528. {    Mouse click.}
  529.  
  530.                         if rMouseDown then
  531.                             ReportMouse(theEvent);
  532.                     mouseUp: 
  533.                         if rMouseUP then
  534.                             begin
  535.                                 DisplayString('Mouse Up');
  536.                                 Displayln;
  537.                             end;
  538.  
  539.                     keyDown:
  540. {    Key event.}
  541.                         if not (excludeLog and (FrontWindow = logWind)) then
  542.                             if rKeyDown then
  543.                                 begin
  544.                                     evtChar := char(BitAnd(theEvent.message, charCodeMask));
  545.                                     evtMods := theEvent.modifiers;
  546.                                     ReportKey(keyDown, evtChar, evtMods, rKDMods);
  547.                                 end;
  548.                     autoKey: 
  549.                         if not (excludeLog and (FrontWindow = logWind)) then
  550.                             if rKeyDown then
  551.                                 begin
  552.                                     evtChar := char(BitAnd(theEvent.message, charCodeMask));
  553.                                     evtMods := theEvent.modifiers;
  554.                                     ReportKey(keyDown, evtChar, evtMods, rKDMods);
  555.                                 end;
  556.                     updateEvt: 
  557.  
  558. {    Update a window.  If it's an update for the log window, invalidate}
  559. {    it, because the message is written and will cause a scroll BEFORE}
  560. {    the window actually gets updated.  This means that part of what}
  561. {    needs redrawing will be scrolled out of the update region and won't}
  562. {    be redrawn properly.  Invalidating the entire port is wasteful but}
  563. {    makes sure the whole window can be drawn properly.}
  564.  
  565.                         begin
  566.                             if WindowPtr(theEvent.message) = logWind then
  567.                                 begin
  568.                                     GetPort(savePort);
  569.                                     SetPort(logWind);
  570.                                     InvalRect(logWind^.portRect);
  571.                                     SetPort(savePort);
  572.                                 end;
  573.                             if not (excludeLog and (WindowPtr(theEvent.message) = logWind)) then
  574.                                 if rUpdate then
  575.                                     begin
  576.                                         ReportUpdate(WindowPtr(theEvent.message));
  577.                                     end;
  578.                         end;
  579.  
  580.                     activateEvt:
  581. {    Activate or deactivate a window.}
  582.  
  583.                         if not (excludeLog and (WindowPtr(theEvent.message) = logWind)) then
  584.                             if rActivate then
  585.                                 begin
  586.                                     ReportActivate(WindowPtr(theEvent.message), theEvent.modifiers);
  587.                                 end;
  588.  
  589.                     diskEvt:
  590. {    handle inserts of uninitialized disks}
  591.  
  592.                         if rDisk then
  593.                             begin
  594.                                 DisplayString('Disk insertion');
  595.                                 if HiWord(theEvent.message) <> noErr then
  596.                                     DisplayString(' (needs initializing)');
  597.                                 Displayln;
  598.                             end;
  599.  
  600. {Added by Ingemar dec -94:}
  601.  
  602. { Suspend/resume events (a.k.a. MultiFinder events)}
  603.  
  604.                     OSevt: 
  605.                         if rMultiFinder then
  606.                             if BAND(BROTL(theEvent.message, 8), $FF) = SuspendResumeMessage then
  607.                                 begin
  608.                                     if BAnd(theEvent.message, 1) <> 0 then
  609.                                         DisplayString('Resume event')
  610.                                     else
  611.                                         DisplayString('Suspend event');
  612.                                     DisplayLn;
  613.                                 end;
  614.  
  615. { Apple Events}
  616.  
  617.                     kHighLevelEvent: 
  618.                         if rAppleEvt then
  619.                             begin
  620.                                 DisplayString('Apple event');
  621.                                 DisplayLn;
  622.                             end;
  623.  
  624.                     nullEvent: 
  625.                         ;  {No point in logging them}
  626.  
  627.                     otherwise
  628.                         begin
  629.                             DisplayString('Unrecognized event.');
  630.                             DisplayLn;
  631.                         end;
  632.                 end; {case}
  633.                 LogEvent := false;
  634.             end;
  635.     end; {LogEvent}
  636.  
  637. {    Background procedure.  Check front window, reset edit menu if window}
  638. {    changes from an application window to a non-application window.}
  639. {    Disable the Edit menu whenever an application window is active,}
  640. {    enable it otherwise.}
  641. {    Also called whenever it is known that the active window has changed.}
  642.  
  643.     procedure CheckFront;
  644.  
  645.         var
  646.             curWind: WindowPtr;
  647.             theKind: integer;
  648.             lastIsApp, curIsApp: Boolean;
  649.             mypeek: WindowPeek;
  650.  
  651.     begin
  652.         curIsApp := false;
  653.         lastIsApp := false;
  654.         curWind := frontwindow;
  655.         if (IsDWindow(lastFront)) or (lastFront = selectWind) then
  656.             lastIsApp := true;
  657.         if (IsDWindow(curWind)) or (curWind = selectWind) then
  658.             curIsApp := true;
  659.         if lastFront <> curWind then
  660.             begin
  661.                 if (IsDWindow(lastFront)) or (lastFront = selectWind) then
  662.                     lastIsApp := true;
  663.                 if (IsDWindow(curWind)) or (curWind = selectWind) then
  664.                     curIsApp := true;
  665.                 if lastIsApp <> curIsApp then
  666.                     begin
  667.                         theKind := 0;
  668.                         if curWind <> nil then
  669.                             begin
  670.                                 mypeek := WindowPeek(curWind);
  671.                                 theKind := mypeek^.windowKind;
  672.                             end;
  673.                         if (curWind = nil) or (theKind < 0) then    { no window or DA in front }
  674.                             EnableItem(editMenu, 0)
  675.                         else
  676.                             DisableItem(editMenu, 0);
  677.                         DrawMenuBar;
  678.                     end;
  679.                 lastFront := curWind;
  680.             end;
  681.     end; {CheckFront}
  682.  
  683. { ------------------------------------------------------------ }
  684. {            Event Selection Window Handler Routines                }
  685. { ------------------------------------------------------------ }
  686.  
  687.  
  688.  
  689. {    Activate event procedure for both display windows and the checkbox}
  690. {    window.}
  691.  
  692.     procedure Activate (active: Boolean);
  693.  
  694.     begin
  695.         CheckFront;
  696.     end;
  697.  
  698. {    Update window.  This is easy, just draw the controls.}
  699.  
  700.     procedure Update (resized: Boolean);
  701.  
  702.     begin
  703.         DrawControls(selectwind);
  704.         GetPort(currentPort);
  705.     end;
  706.  
  707. {    Handle hits in check boxes:}
  708. {    Toggle check box, sync the associated flag, and enable or disable}
  709. {    any subsidiary check boxes accordingly.  (Subsidiaries have}
  710. {    information in the control structure that points back to the owner}
  711. {    check box.)}
  712.  
  713.     procedure Mouse (thePt: Point; t: longint; mods: integer);
  714.  
  715.         var
  716.             ctl: ControlHandle;
  717.             ci: CtrlInfoPtr;
  718.             val: boolean;
  719.             i: integer;
  720.             genericPtr: BooleanPtr;
  721.  
  722.     begin
  723.         if FindControl(thePt, selectWind, ctl) <> 0 then
  724.             if TrackControl(ctl, thePt, nil) <> 0 then
  725.                 begin
  726.                     ci := CtrlInfoPtr(GetCRefcon(ctl));
  727.                     val := not (GetCtlValue(ctl) <> 0);
  728.                     genericPtr := BooleanPtr(ci^.flagAddr);
  729.                     genericPtr^ := val;
  730.                     SetCtlValue(ctl, integer(val));
  731.  
  732.             { enable/disable any subsidiaries }
  733.  
  734.                     for i := 0 to maxButton - 1 do
  735.                         if ctrlInfo[i].subinfo <> nil then
  736.                             if ctrlInfo[i].subInfo^.ctrl = ci^.ctrl then
  737.                                 if val then
  738.                                     HiliteControl(ctrlInfo[i].ctrl, 0)
  739.                                 else
  740.                                     HiliteControl(ctrlInfo[i].ctrl, 255);
  741.                 end
  742.     end; {Mouse}
  743.  
  744. {    File menu handler}
  745.  
  746.     procedure DoFileMenu (item: integer);
  747.  
  748.     begin
  749.         case item of
  750.             showHelp: 
  751.                 begin
  752.                     SelectWindow(helpWind);
  753.                     ShowWindow(helpWind);
  754.                 end;
  755.             showSelect: 
  756.                 begin
  757.                     SelectWindow(selectWind);
  758.                     ShowWindow(selectWind);
  759.                 end;
  760.             showLog: 
  761.                 begin
  762.                     SelectWindow(logWind);
  763.                     ShowWindow(logWind);
  764.                 end;
  765.             quit: 
  766.                 SkelWhoa;
  767.             otherwise
  768.         end;
  769.     end; {DoFileMenu}
  770.  
  771. {    Put the right check marks in the Log menu}
  772.  
  773.     procedure SetLogMenu;
  774.  
  775.     begin
  776.         CheckItem(logMenu, logEvents, reportEvents);
  777.         CheckItem(logMenu, excludeLWind, excludeLog);
  778.         CheckItem(logMenu, wrapStyle, logWrap >= 0);
  779.         CheckItem(logMenu, leftJust, logJust = teJustLeft);
  780.         CheckItem(logMenu, centerJust, logjust = teJustCenter);
  781.         CheckItem(logMenu, rightJust, logJust = teJustRight);
  782.         CheckItem(logMenu, small, logsize = 9);
  783.         CheckItem(logMenu, medium, logsize = 12);
  784.         CheckItem(logMenu, large, logSize = 24);
  785.     end; {SetLogMenu}
  786.  
  787. {    Set display style of log window}
  788.  
  789.     procedure SetStyle;
  790.  
  791.     begin
  792.         SetDWindowStyle(logWind, logFont, logSize, logWrap, logJust);
  793.         SetLogMenu;
  794.     end;
  795.  
  796. {    Log menu handler}
  797.  
  798.     procedure DoLogMenu (item: integer);
  799.  
  800.     begin
  801.         case item of
  802.             logEvents: 
  803.                 begin
  804.                     reportEvents := not reportEvents;
  805.                     SetLogMenu;
  806.                 end;
  807.             excludeLWind: 
  808.                 begin
  809.                     excludeLog := not excludeLog;
  810.                     SetLogMenu;
  811.                 end;
  812.             flushLog: 
  813.                 FlushDWindow(logWind, longint(32767));
  814.             wrapStyle: 
  815.                 begin
  816.                     if logWrap >= 0 then
  817.                         logWrap := -1
  818.                     else
  819.                         logWrap := 0;
  820.                     SetStyle;
  821.                 end;
  822.             leftJust: 
  823.                 begin
  824.                     logJust := teJustLeft;
  825.                     SetStyle;
  826.                 end;
  827.             centerJust: 
  828.                 begin
  829.                     logJust := teJustCenter;
  830.                     SetStyle;
  831.                 end;
  832.             rightJust: 
  833.                 begin
  834.                     logJust := teJustRight;
  835.                     SetStyle;
  836.                 end;
  837.             small: 
  838.                 begin
  839.                     logFont := monaco;
  840.                     logSize := 9;
  841.                     SetStyle;
  842.                 end;
  843.             medium: 
  844.                 begin
  845.                     logFont := systemFont;
  846.                     logSize := 12;
  847.                     SetStyle;
  848.                 end;
  849.             large: 
  850.                 begin
  851.                     logFont := geneva;
  852.                     logSize := 24;
  853.                     SetStyle;
  854.                 end;
  855.             top: 
  856.                 SetDWindowPos(logWind, 0);
  857.             bottom: 
  858.                 SetDWindowPos(logWind, 32767);
  859.             otherwise
  860.         end;
  861.     end; {DoLogMenu}
  862.  
  863. {    Handle selection of About… item from Apple menu}
  864.  
  865.     procedure DoAbout;
  866.  
  867.         var
  868.             ignore: integer;
  869.  
  870.     begin
  871.         ignore := Alert(aboutAlrtRes, nil);
  872.     end;
  873.  
  874. {    Dispose of event selection window (and controls)}
  875.  
  876.     procedure WClobber;
  877.  
  878.     begin
  879.         DisposeWindow(selectWind);
  880.     end;
  881.  
  882. {    Create controls}
  883.  
  884.     procedure MakeControls (theWind: windowPtr);
  885.  
  886.         var
  887.             i: integer;
  888.             ci: CtrlInfoPtr;
  889.             r: Rect;
  890.             genericPtr: booleanPtr;
  891.  
  892.     begin
  893.         for i := 0 to maxButton - 1 do
  894.             begin
  895.                 ci := @ctrlInfo[i];
  896.                 SetRect(r, ci^.loc.h, ci^.loc.v, ci^.loc.h + StringWidth(ci^.title) + 30, ci^.loc.v + 20);
  897.                 genericPtr := ci^.flagAddr;
  898.                 ci^.ctrl := NewControl(theWind, r, ci^.title, true, integer(genericPtr^), 0, 1, checkBoxProc, longint(ci));
  899.             end;
  900.         ValidRect(theWind^.portRect);
  901.     end;
  902.  
  903. begin
  904.     SetupStuff;
  905.     SkelInit(6, nil);
  906.     TransDisplayInit;
  907.     SkelApple('About EventLog...', @DoAbout);
  908.     fileMenu := GetMenu(fileMenuRes);
  909.     dummy := SkelMenu(fileMenu, @DoFileMenu, nil, false);
  910.  
  911.     editMenu := GetMenu(editMenuRes);
  912.     DisableItem(editmenu, 0);
  913.     dummy := SkelMenu(editMenu, nil, nil, false);
  914.  
  915.     logMenu := GetMenu(logMenuRes);
  916.     dummy := Skelmenu(logMenu, @DoLogmenu, nil, true);
  917.  
  918. {    Create windows and install handlers.}
  919.  
  920.     SetDwindowNotify(nil, @Activate);
  921.  
  922.     helpWind := GetNewDWindow(helpWindRes, WindowPtr(-1));
  923.     SetDWindowStyle(helpWind, 0, 0, 0, teJustLeft);
  924.  
  925.     h := GetResource('TEXT', helpTextRes);    { read help text }
  926.     HLock(h);                            { lock it and write to window }
  927.     DisplayText(h^, GetHandleSize(h));
  928.     HUnlock(h);
  929.     ReleaseResource(h);                { done with it, so goodbye }
  930.     SetDWindowPos(helpWind, 0);        { scroll back to top }
  931.     ShowWindow(helpWind);
  932.  
  933.     logWind := GetNewDWindow(logWindRes, WindowPtr(-1));
  934.  
  935.     SkelEventHook(@LogEvent);
  936.     reportEvents := true;
  937.     excludeLog := false;
  938.  
  939.     logFont := monaco;
  940.     logSize := 9;
  941.     logWrap := 0;
  942.     logJust := teJustLeft;
  943.     SetStyle;
  944.     ShowWindow(logWind);
  945.  
  946.     selectWind := GetNewWindow(selectWindRes, nil, WindowPtr(-1));
  947.  
  948.     dummy := SkelWindow(selectWind, @Mouse, nil, @Update, @Activate, nil, @WClobber, nil, true);
  949.         { the window }
  950.         { mouse click handler }
  951.         { key clicks are ignored }
  952.         { window updating procedure }
  953.         { window activate/deactivate procedure }
  954.         { hide window }
  955.         { window disposal procedure }
  956.         { idle proc }
  957.         { irrelevant }
  958.  
  959.     MakeControls(selectWind);
  960.  
  961. {    Process events until user quits,}
  962. {    then clean up and exit}
  963.  
  964.     CheckFront;
  965.     SelectWindow(helpWind); {Bug: This doesn't change the port to the front window!}
  966.     SetPort(helpWind);
  967.     SkelBackground(@CheckFront);
  968.     SkelMain;
  969.     SkelClobber;
  970. end.